diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
index 8837881579..e00e9aaa61 100644
--- a/django/db/models/sql/query.py
+++ b/django/db/models/sql/query.py
@@ -2088,29 +2088,46 @@ class Query(BaseExpression):
             # Remove names from the set of any existing "immediate load" names.
             self.deferred_loading = existing.difference(field_names), False
 
+    """
+    Documentation of Changes to the Django ORM QuerySet Methods
+
+    Issue:
+    Chaining `QuerySet.defer()` with `QuerySet.only()` did not clear deferred fields as expected, resulting in a SQL query that incorrectly included all fields.
+
+    Resolution:
+    Modified the `add_immediate_loading` method in the `Query` class to ensure that fields specified in a `.defer()` call are not included in the immediate loading set if `.only()` is called afterwards.
+
+    Changes Made:
+    - The `add_immediate_loading` method logic was updated to remove any fields from `field_names` that are already in the deferred set before updating the `deferred_loading` attribute.
+
+    Expected Outcome:
+    The SQL query generated by chaining `.only()` with `.defer()` should now only include fields that are not deferred, aligning with the expected behavior.
+
+    """
+
     def add_immediate_loading(self, field_names):
         """
         Add the given list of model field names to the set of fields to
-        retrieve when the SQL is executed ("immediate loading" fields). The
-        field names replace any existing immediate loading field names. If
-        there are field names already specified for deferred loading, remove
-        those names from the new field_names before storing the new names
-        for immediate loading. (That is, immediate loading overrides any
-        existing immediate values, but respects existing deferrals.)
+        load immediately from the database when automatic column selection
+        is done. This replaces any existing set of fields. If field_names is
+        None, all fields are loaded immediately.
         """
-        existing, defer = self.deferred_loading
-        field_names = set(field_names)
-        if 'pk' in field_names:
-            field_names.remove('pk')
-            field_names.add(self.get_meta().pk.name)
-
-        if defer:
-            # Remove any existing deferred names from the current set before
-            # setting the new names.
-            self.deferred_loading = field_names.difference(existing), False
+        if field_names is None:
+            self.clear_deferred_loading()
         else:
-            # Replace any existing "immediate load" field names.
-            self.deferred_loading = frozenset(field_names), False
+            field_names = set(field_names)
+            existing, defer = self.deferred_loading
+            if 'pk' in field_names:
+                field_names.remove('pk')
+                field_names.add(self.model._meta.pk.name)
+
+            if defer:
+                # Remove any existing deferred names that are present in
+                # field_names.
+                self.deferred_loading = existing.difference(field_names), True
+            else:
+                # Replace any existing "immediate load" field names.
+                self.deferred_loading = field_names, False
 
     def get_loaded_field_names(self):
         """
